#include <algorithm>

#include "app.hh"
#include "../worker/worker.hh"
#include "../utils/painter.hh"
#include "../utils/graph.hh"
#include "../utils/debug.hh"

void icesp::app::run(configuration::config const& conf)
{
    for (auto& name_case : conf.cases) {
        auto& name = name_case.first;
        auto& case_ = name_case.second;

        // DEBUG("case: " << name << " started.");
        PRINT("\n================================================================\n");
        PRINT3("case: ", name, " started.\n");

        units::graph_source_point source(case_.source);
        units::graph_target_point target(case_.target);
        auto const& bdd = case_.bfs_delta_depth;
        units::thread_count nthreads(case_.nthreads);
        units::run_times ntimes(case_.ntimes);
        units::relax_count_per_iter nrelax(case_.nrelax);
        auto const& graph_path = case_.graph_path;
        auto renumbering = case_.renumbering;
        graph::adj_matrix g(graph_path);

        PRINT("config:\n");
        PRINT2("thread number: ", case_.nthreads);
        PRINT2(", nrelax: ", case_.nrelax);
        PRINT2(", bfs delta depath: ", case_.bfs_delta_depth << "\n");

        painter p;

        p.bfs_delta_depth_coloring(g, source.value, bdd);

        painter pad;
        if (renumbering) {
            auto max = *std::max_element(p.get_colors(), p.get_colors() + g.n);
            p.refine(max + 1);
            renumber(g, p);
            source.value = g.index[source.value];
            p.refine(nthreads.value);
            renumber(g, p);
            source.value = g.index[source.value];
        } else {
            p.refine(nthreads.value);
        }
        g.pad(4, p.colors);
        g.realloc_result_pad();
        pad.from_array(g.n_after_pad, g.pad_color);
        pad.refine(nthreads.value);

        // TODO init graph pad

        PRINT3("initialization: ", "done", ".\n");
        worker::run(name, ntimes, nthreads, nrelax, g, source, target, p, pad);
    }
}

